#include "depui/depui.h"

#ifdef MX_PLATFORM_DEGFX

#   include "degfx/degfx.h"

extern void mx__degfx_textchunks(const MX_TEXTUAL_DATA * textual, MX_PIXEL fore, int x, int y);

#   define MXMODULE_BITLINE
#   define MXMODULE_BITDRAW
#   define MXMODULE_FONTDRAW
#   define MXMODULE_LOADFONT
#   define MXMODULE_LOADTGA
#   define MXMODULE_DECORATE
#   define MXMODULE_SLIDER

static MX_PIXEL mx_theme_rounded_buttontgadata[] = {
	MXRGBT(252, 250, 252, 250), MXRGBT(244, 250, 252, 250), MXRGBT(244,
																   246,
																   252,
																   250),
	MXRGBT(228, 230, 244, 250), MXRGBT(228, 230,
									   244, 250),
	MXRGBT(228, 230, 236, 250), MXRGBT(236, 238, 244, 250), MXRGBT(236,
																   238,
																   244,
																   250),
	MXRGBT(236, 238, 252, 250), MXRGBT(228,
									   222,
									   236,
									   250),
	MXRGBT(220, 222, 236, 250), MXRGBT(212, 218, 228, 250),
	MXRGBT(244, 246, 252, 250), MXRGBT(236, 234, 244, 250), MXRGBT(220,
																   222,
																   228,
																   250),
	MXRGBT(196, 162, 164, 207), MXRGBT(188, 118,
									   124, 104),
	MXRGBT(188, 82, 68, 21), MXRGBT(204, 90, 84, 25), MXRGBT(220, 130, 124,
															 107),
	MXRGBT(244,
		   190,
		   188,
		   220),
	MXRGBT(244, 242, 252,
		   250),
	MXRGBT(228, 230, 236, 250), MXRGBT(212, 214, 228, 250),
	MXRGBT(244, 242, 252, 250), MXRGBT(220, 218, 228, 250), MXRGBT(172,
																   134,
																   140,
																   178),
	MXRGBT(156, 66, 68, 0), MXRGBT(180, 70, 60, 0),
	MXRGBT(212, 82, 68, 0), MXRGBT(228, 90, 68, 0), MXRGBT(236, 98, 68, 0),
	MXRGBT(228, 94, 60, 4), MXRGBT(244, 174, 164, 194),
	MXRGBT(236, 238, 244, 250), MXRGBT(212, 214, 220, 250),
	MXRGBT(228, 230, 244, 250), MXRGBT(180, 150, 156, 207), MXRGBT(148, 66,
																   68,
																   11),
	MXRGBT(204, 78, 68, 0), MXRGBT(252, 126, 108, 0),
	MXRGBT(252, 182, 156, 0), MXRGBT(252, 182, 140, 0), MXRGBT(252, 118,
															   76,
															   0),
	MXRGBT(252, 126, 76, 0), MXRGBT(244, 106, 60, 25),
	MXRGBT(252, 198, 188, 233), MXRGBT(228, 230, 244, 250),
	MXRGBT(212, 214, 220, 250), MXRGBT(156, 110, 116, 101), MXRGBT(188, 70,
																   60,
																   0),
	MXRGBT(252, 142, 132, 0), MXRGBT(252, 248, 195, 0),
	MXRGBT(252, 213, 179, 0), MXRGBT(252, 201, 155, 0), MXRGBT(252, 163,
															   92,
															   0),
	MXRGBT(252, 138, 76, 0), MXRGBT(252, 130, 68, 0),
	MXRGBT(236, 150, 124, 131), MXRGBT(236, 238, 252, 250),
	MXRGBT(204, 206, 212, 250), MXRGBT(140, 74, 76, 62), MXRGBT(244, 98,
																92,
																0),
	MXRGBT(252, 178, 164, 0), MXRGBT(253, 208, 174, 0),
	MXRGBT(252, 193, 151, 0), MXRGBT(252, 191, 134, 0), MXRGBT(253, 181,
															   89,
															   0),
	MXRGBT(252, 182, 76, 0), MXRGBT(252, 146, 68, 0),
	MXRGBT(236, 110, 76, 79), MXRGBT(244, 250, 252, 250),
	MXRGBT(196, 202, 212, 250), MXRGBT(132, 58, 60, 51), MXRGBT(252, 110,
																108,
																0),
	MXRGBT(252,
		   194,
		   172,
		   0),
	MXRGBT(252, 184, 153, 0),
	MXRGBT(252, 180, 134, 0), MXRGBT(252, 180, 114, 0), MXRGBT(252, 190,
															   100,
															   0),
	MXRGBT(252,
		   214,
		   100,
		   0),
	MXRGBT(252, 154, 76,
		   0), MXRGBT(236,
					  98,
					  60,
					  44),
	MXRGBT(244, 246, 252, 241),
	MXRGBT(204, 202, 220, 250), MXRGBT(132, 74, 76, 79), MXRGBT(252, 114,
																108,
																0),
	MXRGBT(252,
		   198,
		   156,
		   0),
	MXRGBT(252, 177, 142, 0),
	MXRGBT(252, 170, 123, 0), MXRGBT(252, 172, 106, 0), MXRGBT(252, 190,
															   102,
															   0),
	MXRGBT(252,
		   214,
		   100,
		   0),
	MXRGBT(252, 146, 68,
		   0), MXRGBT(236,
					  110,
					  76,
					  62),
	MXRGBT(244, 246, 252, 250),
	MXRGBT(220, 218, 228, 250), MXRGBT(156, 106, 108, 131), MXRGBT(236, 90,
																   84,
																   0),
	MXRGBT(252, 138, 124, 0), MXRGBT(251, 148, 123, 0),
	MXRGBT(249, 147, 105, 0), MXRGBT(252, 155, 95, 0), MXRGBT(252, 180, 99,
															  0),
	MXRGBT(252, 210, 100, 0), MXRGBT(252, 126, 68, 0),
	MXRGBT(244, 150, 132, 101), MXRGBT(236, 238, 252, 250),
	MXRGBT(228, 226, 236, 250), MXRGBT(180, 154, 164, 233), MXRGBT(172, 66,
																   60,
																   25),
	MXRGBT(236, 90, 84, 0), MXRGBT(252, 126, 108, 0),
	MXRGBT(236, 110, 76, 0), MXRGBT(252, 126, 76, 0), MXRGBT(252, 170, 100,
															 0),
	MXRGBT(252, 142, 68, 0), MXRGBT(244, 106, 60, 11),
	MXRGBT(244, 194, 188, 207), MXRGBT(236, 234, 244, 250),
	MXRGBT(244, 246, 252, 250), MXRGBT(220, 218, 228, 250), MXRGBT(172,
																   134,
																   140,
																   194),
	MXRGBT(164, 66, 60, 4), MXRGBT(188, 78, 68, 0),
	MXRGBT(188, 82, 68, 0), MXRGBT(220, 94, 76, 0), MXRGBT(220, 94, 76, 0),
	MXRGBT(236, 98, 68, 0), MXRGBT(244, 170, 156, 178),
	MXRGBT(244, 242, 252, 250), MXRGBT(220, 222, 228, 250),
	MXRGBT(244, 246, 252, 250), MXRGBT(236, 238, 252, 250), MXRGBT(220,
																   222,
																   228,
																   250),
	MXRGBT(196, 162, 164, 220), MXRGBT(188, 114,
									   116, 107),
	MXRGBT(188, 82, 68, 25), MXRGBT(196, 86, 76, 21), MXRGBT(220, 134, 124,
															 104),
	MXRGBT(236,
		   186,
		   180,
		   207),
	MXRGBT(244, 242, 252,
		   250),
	MXRGBT(220, 222, 228, 250), MXRGBT(220, 218, 228, 250),
	MXRGBT(252, 250, 252, 250), MXRGBT(244, 246, 252, 250), MXRGBT(236,
																   238,
																   244,
																   250),
	MXRGBT(236, 234, 244, 250), MXRGBT(220, 226,
									   236, 250),
	MXRGBT(236, 234, 244, 250), MXRGBT(228, 230, 236, 250), MXRGBT(236,
																   238,
																   252,
																   250),
	MXRGBT(236, 238, 244, 250), MXRGBT(220,
									   222,
									   228,
									   250),
	MXRGBT(212, 218, 228, 250), MXRGBT(220, 218, 228, 250),
	0
};

static MX_BITMAP mx_theme_rounded_buttontga = MXBITMAP_DECLARE(mx_theme_rounded_buttontgadata, 12, 13);

static MX_BITMAP *mx_theme_rounded_buttonup;
static MX_BITMAP *mx_theme_rounded_buttondown;
static MX_BITMAP *mx_theme_rounded_buttonarmed;
static MX_BITMAP *mx_theme_rounded_buttondisabled;

static void mx_theme_rounded_stop(void)
{
	mx_delete(mx_theme_rounded_buttondown);
	mx_theme_rounded_buttondown = 0;
	mx_delete(mx_theme_rounded_buttonarmed);
	mx_theme_rounded_buttonarmed = 0;
	mx_delete(mx_theme_rounded_buttondisabled);
	mx_theme_rounded_buttondisabled = 0;
}

static unsigned mx_theme_rounded_start(void)
{
	MX_BITMAP_ITER begin;
	MX_BITMAP_ITER end;

	mx_theme_rounded_buttonup = &mx_theme_rounded_buttontga;

	mx_theme_rounded_buttondown = mx_bitmap_clone(mx_theme_rounded_buttonup);
	begin = mx_bitmap_begin(mx_theme_rounded_buttondown);
	end = mx_bitmap_end(mx_theme_rounded_buttondown);
	while (begin != end) {
		unsigned long r = MXR(*begin);
		unsigned long g = MXG(*begin);
		unsigned long b = MXB(*begin);
		unsigned long t = MXT(*begin);

		r = MX_MIN(r + 45, 0xff);
		g = MX_MIN(g + 45, 0xff);
		b = MX_MIN(b + 45, 0xff);
		*begin++ = MXRGBT(r, g, b, t);
	}

	mx_theme_rounded_buttonarmed = mx_bitmap_clone(mx_theme_rounded_buttonup);
	begin = mx_bitmap_begin(mx_theme_rounded_buttonarmed);
	end = mx_bitmap_end(mx_theme_rounded_buttonarmed);
	while (begin != end) {
		unsigned long r = MXR(*begin);
		unsigned long g = MXG(*begin);
		unsigned long b = MXB(*begin);
		unsigned long t = MXT(*begin);

		r = MX_MIN(r + 25, 0xff);
		g = MX_MIN(g + 25, 0xff);
		b = MX_MIN(b + 25, 0xff);
		*begin++ = MXRGBT(r, g, b, t);
	}

	mx_theme_rounded_buttondisabled = mx_bitmap_clone(mx_theme_rounded_buttonup);
	begin = mx_bitmap_begin(mx_theme_rounded_buttondisabled);
	end = mx_bitmap_end(mx_theme_rounded_buttondisabled);
	while (begin != end) {
		const unsigned long grey = (MXR(*begin) + MXG(*begin) + MXB(*begin)) / 3;
		unsigned long t = MXT(*begin);

		*begin++ = MXRGBT(grey, grey, grey, t);
	}

	if ((!mx_theme_rounded_buttonup) || (!mx_theme_rounded_buttondown)
		|| (!mx_theme_rounded_buttonarmed)
		|| (!mx_theme_rounded_buttondisabled)) {
		mx_theme_rounded_stop();
		return false;
	}
	return true;
}

static void mx_theme_rounded_event(void)
{
	if (mx.event == MX_DEFAULTRECT) {
		MX_RECT *rect = mx_defaultrect_data();
		const int w = MX_MAX(mx_w(mx_theme_rounded_buttonup), 10);
		const int h = MX_MAX(mx_h(mx_theme_rounded_buttonup), 10);

		/* For a close or resize button make it so big as the bitmap */
		if ((MXID(mx.obj) == MXID_WINCLOSE)
			|| (MXID(mx.obj) == MXID_WINRESIZE)) {

			rect->x2 = rect->x1 + w;
			rect->y2 = rect->y1 + h;
			return;

			/* Text button has to have room for text */
		} else if (MXCLASS(mx.obj) == mx_button_class) {
			MX_BUTTON *button = (MX_BUTTON *) mx.obj;

			rect->x2 = rect->x1 + MXTEXTUAL(button)->_textwidth + 10;
			rect->y2 = rect->y1 + MXTEXTUAL(button)->_textheight + 6;
			return;

			/* For a border, make it a bit wider and taller */
		} else if (MXCLASS(mx.obj) == mx_winborder_class) {
			mx__event_default();
			rect->x1 -= 3;
			rect->y1 -= 3;
			rect->x2 += 3;
			rect->y2 += 3;
			return;

			/* For a list element make it a bit wider and taller */
		} else if (MXCLASS(mx.obj) == mx_listelem_class) {
			mx__event_default();
			rect->x2 += 2;
			rect->y2 += 2;
			return;

			/* Sliders have to have a minimum width/ height */
		} else if (MXCLASS(mx.obj) == mx_vslider_class) {
			MX_SLIDER *slider = (MX_SLIDER *) mx.obj;

			slider->base.slider._min = w;
			rect->x2 = rect->x1 + w;
			return;

		} else if (MXCLASS(mx.obj) == mx_hslider_class) {
			MX_SLIDER *slider = (MX_SLIDER *) mx.obj;

			slider->base.slider._min = h;
			rect->y2 = rect->y1 + h;
			return;
		}

		/* Make list elements show who has the pointer */
	} else if ((mx.event == MX_POINTER_ENTER)
			   && (MXCLASS(mx.obj) == mx_listelem_class)) {
		mx_dirty(mx.obj, true);

	} else if ((mx.event == MX_POINTER_LEAVE)
			   && (MXCLASS(mx.obj) == mx_listelem_class)) {
		mx_dirty(mx.obj, true);
	}

	mx__event_default();
}

static void mx_theme_rounded_obj(MX_OBJ * obj)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(obj);

		mx_rectfill(objrect->x1, objrect->y1, objrect->x2, objrect->y2, MXRGB(0, 0, 128));
	}
}

static void mx_theme_rounded_vslider(MX_SLIDER * slider)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(slider);
		MX_BITMAP *bit = mx_theme_rounded_buttonup;

		mx_rectfill(objrect->x1, objrect->y1, objrect->x2, objrect->y2, MXCOLOR_wheat);
		mx_decorate(mx_theme_rounded_buttondisabled, MXDEFAULT, MXDEFAULT, objrect->x1, objrect->y1, objrect->x2, objrect->y2);

		if (mx_armed(slider))
			bit = mx_theme_rounded_buttondown;
		if (mx_disabled(slider))
			bit = mx_theme_rounded_buttondisabled;

		mx_decorate(bit, MXDEFAULT, MXDEFAULT, objrect->x1, objrect->y1 + slider->base.slider._upper, objrect->x2,
					objrect->y1 + slider->base.slider._lower);
	}
}

static void mx_theme_rounded_hslider(MX_SLIDER * slider)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(slider);
		MX_BITMAP *bit = mx_theme_rounded_buttonup;

		mx_rectfill(objrect->x1, objrect->y1, objrect->x2, objrect->y2, MXCOLOR_wheat);
		mx_decorate(mx_theme_rounded_buttondisabled, MXDEFAULT, MXDEFAULT, objrect->x1, objrect->y1, objrect->x2, objrect->y2);

		if (mx_armed(slider))
			bit = mx_theme_rounded_buttondown;
		if (mx_disabled(slider))
			bit = mx_theme_rounded_buttondisabled;

		mx_decorate(bit, MXDEFAULT, MXDEFAULT, objrect->x1 + slider->base.slider._upper, objrect->y1, objrect->x1 + slider->base.slider._lower,
					objrect->y2);
	}
}

static MX_PIXEL mx_theme_rounded_textual_background(const MX_TEXTUAL_DATA * textual, int x1, int y1, int x2, int y2, unsigned armable)
{
	MX_PIXEL fore = MXCOLOR_black;
	MX_PIXEL back = MXCOLOR_white;

	if (mx_selected(textual))
		back = MXCOLOR_wheat1;

	if (mx_disabled(textual))
		fore = MXCOLOR_grey50;

	if ((armable) && (mx_armed(textual)))
		back = MXCOLOR_grey50;

	mx_rectfill(x1, y1, x2, y2, back);

	return fore;
}

static void mx_theme_rounded_textual(MX_TEXTUAL * text)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(text);

		MX_PIXEL fore = mx_theme_rounded_textual_background(MXTEXTUAL(text),
															objrect->x1,
															objrect->y1,
															objrect->x2,
															objrect->y2,
															false);

		mx__degfx_textchunks(MXTEXTUAL(text), fore, 0, 0);
	}
}

static void mx_theme_rounded_scrollcorner(MX_OBJ * scrollcorner)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(scrollcorner);

		mx_rectfill(objrect->x1, objrect->y1, objrect->x2, objrect->y2, MXCOLOR_wheat);
	}
}

static void mx_theme_rounded_scroll(MX_SCROLL * scroll)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(scroll);

		mx_rectfill(objrect->x1, objrect->y1, objrect->x2, objrect->y2, MXCOLOR_white);
	}
}

static void mx_theme_rounded_button(MX_BUTTON * button)
{
	mx_expose_background(0);

	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(button);
		int offset = 0;
		const MX_BITMAP *bit = mx_theme_rounded_buttonup;

		if (mx_disabled(button)) {
			bit = mx_theme_rounded_buttondisabled;

		} else if (mx_armed(button)) {
			bit = mx_theme_rounded_buttonarmed;

		} else if (mx_selected(button)) {
			bit = mx_theme_rounded_buttondown;
			offset = 1;
		}

		mx_decorate(bit, MXDEFAULT, MXDEFAULT, objrect->x1, objrect->y1, objrect->x2, objrect->y2);

		mx__degfx_textchunks(MXTEXTUAL(button), MXCOLOR_black, 5 + offset, 3 + offset);
	}
}

void mx_theme_rounded_listelem(MX_LISTELEM * listelem)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(listelem);

		MX_PIXEL fore = mx_theme_rounded_textual_background(MXTEXTUAL(listelem),
															objrect->x1,
															objrect->y1,
															objrect->x2,
															objrect->y2, true);

		if (mx_haspointer(listelem))
			mx_box(objrect->x1, objrect->y1, objrect->x2, objrect->y2, 1, MXCOLOR_grey50, MXCOLOR_grey50);

		mx__degfx_textchunks(MXTEXTUAL(listelem), fore, 1, 1);
	}
}

static void mx_theme_rounded_root(MX_WIN * root)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(root);

		mx_rectfill(objrect->x1, objrect->y1, objrect->x2, objrect->y2, MXCOLOR_lightskyblue);
	}
}

static void mx_theme_rounded_winborder(MX_WINBORDER * border)
{
	mx_expose_background(0);

	if (mx_exposing()) {
		MX_WIN *owner = MXOBJ(border)->_win;
		const MX_RECT *objrect = MXRECT(border);
		MX_BITMAP *bit = mx_theme_rounded_buttonup;

		if (mx_active(owner))
			bit = mx_theme_rounded_buttondown;

		if (mx_disabled(owner))
			bit = mx_theme_rounded_buttondisabled;

		mx_decorate(bit, MXDEFAULT, MXDEFAULT, objrect->x1, objrect->y1, objrect->x2, objrect->y2);

		if (owner)
			mx__degfx_textchunks(MXTEXTUAL(owner), MXCOLOR_black, mx_x(border) - mx_x(owner) + 5, mx_y(border) - mx_y(owner) + 3);
	}
}

static void mx_theme_rounded_win(MX_WIN * win)
{
	if (mx_exposing()) {
		const MX_RECT *objrect = MXRECT(win);

		mx_rectfill(objrect->x1, objrect->y1, objrect->x2, objrect->y2, MXCOLOR_wheat);
	}
}

const MX_THEME mx_theme_rounded = {
	mx_theme_rounded_start,
	mx_theme_rounded_stop,
	mx_theme_rounded_event,
	mx_theme_rounded_obj,
	mx_theme_rounded_vslider,
	mx_theme_rounded_hslider,
	mx_theme_rounded_textual,
	mx_theme_rounded_scrollcorner,
	mx_theme_rounded_scroll,
	mx_theme_rounded_button,
	mx_theme_rounded_listelem,
	mx_theme_rounded_root,
	mx_theme_rounded_winborder,
	mx_theme_rounded_win
};

#endif
